package judesart.app.server;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import judesart.app.service.ImageService;
import judesart.common.bean.ApplicationContextProvider;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.images.Image;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;

public class ImagesDownloadServlet extends HttpServlet implements Servlet {
    private final static Log LOGGER = LogFactory.getLog(ImagesDownloadServlet.class);
    final static String RFC1123_DATE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss zzz";

    ImageService imageService = ApplicationContextProvider.getCtx().getBean(
            ImageService.class);
    MemcacheService memcacheService = MemcacheServiceFactory.getMemcacheService("jaw-images");
    BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        LOGGER.debug(" > ImagesDownloadServlet.doGet [" + req.getQueryString()
                + "]");

        Image image;
        String path = req.getPathInfo();
        if (path == null){
        	path = "";
        }
        LOGGER.debug("path i: [" + path + "]");
    	String key = path + '?' + req.getQueryString();
        if (memcacheService.contains(key)) {
            image = (Image) memcacheService.get(key);
        } else {
        	Pattern pattern = Pattern.compile("^/(\\d*)_?(\\d{1,4}x\\d{1,4})?_?(crop)?$");
        	Matcher matcher = pattern.matcher(path);
            String imageId = null;
            String size = null;
            boolean crop = false;
        	if(matcher.matches()){
        		imageId = matcher.group(1);
        		if (matcher.groupCount() > 1){
        			size = matcher.group(2);
        		}
        		if (matcher.groupCount() > 2 && "crop".equals(matcher.group(3))){
        			crop = true;
        		}
        	} else {
        		imageId = req.getParameter("id");
                size = req.getParameter("size");
                crop = req.getParameter("crop")!=null && "true".equalsIgnoreCase(req.getParameter("crop"));
        	}
        	LOGGER.debug("image id: [" + imageId + "] size: [" + size + "] crop: [" + crop + "]");
            Integer width = null;
            Integer height = null;
            if (size != null) {
                String[] split = size.trim().split("x");
                if (split.length > 1) {
                    width = Integer.parseInt(split[0]);
                    height = Integer.parseInt(split[1]);
                }
            }
            try {
                image = imageService.getImageConstrained(new Long(imageId),
                        width, height, crop);
                try {
                    memcacheService.put(req.getQueryString(), image);
                } catch (Throwable e) {
                    LOGGER.error("Unable to put image in cache", e);
                }
            } catch (NumberFormatException e) {
                LOGGER.debug("invalid image id [" + imageId + "]");
                image = null;
            }
        }
        if (image != null) {
            resp.setContentType("image/" + image.getFormat().name());
            resp.setHeader("Cache-Control", "public, max-age: 31104000");
            SimpleDateFormat dateFormat = new SimpleDateFormat(RFC1123_DATE_PATTERN);
            Date date = new Date(System.currentTimeMillis() + 31104000000L);
            resp.setHeader("Expires", dateFormat.format(date));
            LOGGER.debug(" > resp.setContentType " + "image/"
                    + image.getFormat().name());
            LOGGER.debug(" > image.getData() " + image.getImageData().length);
            resp.getOutputStream().write(image.getImageData());
        }
    }
}
